package rexsee.multimedia;

import rexsee.core.browser.Browser;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout;

public class VideoView extends SurfaceView {

	private static final String CLASS_NAME = "VideoView";

	public static final String EVENT_ONVIDEOBUFFERINGUPDATED = "onVideoBufferingUpdated";
	public static final String EVENT_ONVIDEOPLAYCOMPLETED = "onVideoPlayCompleted";
	public static final String EVENT_ONVIDEOPLAYERINFO = "onVideoPlayerInfo";
	public static final String EVENT_ONVIDEOSEEKCOMPLETED = "onVideoSeekCompleted";
	public static final String EVENT_ONVIDEOSIZECHANGED = "onVideoSizeChanged";
	public static final String EVENT_ONVIDEOSURFACECREATED = "onVideoSurfaceCreated";

	private final Context mContext;
	private final Browser mBrowser;
	private final String mId;

	public String path;
	public boolean isLooping;
	public boolean isKeepScale;
	public MediaPlayer mediaPlayer = null;

	private int mVideoWidth = 0;
	private int mVideoHeight = 0;

	public VideoView(Browser browser, final String id, String url, boolean looping, boolean keepScale) {

		super(browser.getContext());

		mContext = browser.getContext();
		mBrowser = browser;
		mId = id;
		path = url;
		isLooping = looping;
		isKeepScale = keepScale;

		mBrowser.eventList.add(EVENT_ONVIDEOBUFFERINGUPDATED);
		mBrowser.eventList.add(EVENT_ONVIDEOPLAYCOMPLETED);
		mBrowser.eventList.add(EVENT_ONVIDEOPLAYERINFO);
		mBrowser.eventList.add(EVENT_ONVIDEOSEEKCOMPLETED);
		mBrowser.eventList.add(EVENT_ONVIDEOSIZECHANGED);
		mBrowser.eventList.add(EVENT_ONVIDEOSURFACECREATED);

		getHolder().addCallback(new SurfaceHolder.Callback() {
			@Override
			public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
			}
			@Override
			public void surfaceCreated(SurfaceHolder holder) {
				if (mId != null) {
					mBrowser.eventList.run(EVENT_ONVIDEOSURFACECREATED, new String[]{mId});
				} else {
					mBrowser.eventList.run(EVENT_ONVIDEOSURFACECREATED);
				}
				openVideo();
			}
			@Override
			public void surfaceDestroyed(SurfaceHolder holder) {
				if (mediaPlayer != null) {
					mediaPlayer.reset();
					mediaPlayer.release();
					mediaPlayer = null;
				}
			}
		});
		getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		getHolder().setFixedSize(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT);
		setFocusable(true);
		setFocusableInTouchMode(true);
		requestFocus();
		requestLayout();
		invalidate();

	}

	public void openVideo() {
		if (path == null || path.trim().equals("")) { return; }
		Intent i = new Intent("com.android.music.musicservicecommand");
		i.putExtra("command", "pause");
		mContext.sendBroadcast(i);
		if (mediaPlayer != null) {
			mediaPlayer.reset();
			mediaPlayer.release();
			mediaPlayer = null;
		}
		Uri uri;
		if (path.startsWith("raw://")) {
			Resources r = mContext.getResources();
			String packageName = mContext.getPackageName();
			int id = r.getIdentifier(path.substring(6), "raw", packageName);
			if (id == 0) {
				mBrowser.exception(this.getClass().getName(), "The specified resource does not found.");
				return;
			}
			uri = Uri.parse("android.resource://" + packageName + "/" + id);
		} else {
			uri = Uri.parse(path);
		}
		try {
			mediaPlayer = new MediaPlayer();
			mediaPlayer.setLooping(isLooping);
			mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
				@Override
				public void onBufferingUpdate(MediaPlayer mp, int percent) {
					if (mId != null) {
						mBrowser.eventList.run(EVENT_ONVIDEOBUFFERINGUPDATED, new String[]{mId, String.valueOf(percent)});
					} else {
						mBrowser.eventList.run(EVENT_ONVIDEOBUFFERINGUPDATED, new String[]{String.valueOf(percent)});
					}
				}
			});
			mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
				@Override
				public void onCompletion(MediaPlayer mp) {
					if (path.trim().equals("")) return;
					if (mId != null) {
						mBrowser.eventList.run(EVENT_ONVIDEOPLAYCOMPLETED, new String[]{mId});
					} else {
						mBrowser.eventList.run(EVENT_ONVIDEOPLAYCOMPLETED);
					}
				}
			});
			mediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
				@Override
				public void onSeekComplete(MediaPlayer mp) {
					if (mId != null) {
						mBrowser.eventList.run(EVENT_ONVIDEOSEEKCOMPLETED, new String[]{mId});
					} else {
						mBrowser.eventList.run(EVENT_ONVIDEOSEEKCOMPLETED);
					}
				}
			});
			mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
				@Override
				public boolean onError(MediaPlayer mp, int what, int extra) {
					mBrowser.exception(CLASS_NAME, decodeMediaError(what, extra));
					return false;
				}
			});
			mediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
				@Override
				public boolean onInfo(MediaPlayer mp, int what, int extra) {
					String msg = decodeMediaInfo(what, extra);
					if (mId != null) {
						mBrowser.eventList.run(EVENT_ONVIDEOPLAYERINFO, new String[]{mId, msg});
					} else {
						mBrowser.eventList.run(EVENT_ONVIDEOPLAYERINFO, new String[]{msg});
					}
					return false;
				}
			});
			mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
				@Override
				public void onPrepared(MediaPlayer mp) {
					mediaPlayer.start();
				}
			});
			mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
				@Override
				public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
					if (isKeepScale) {
						mVideoWidth = mp.getVideoWidth();
						mVideoHeight = mp.getVideoHeight();
						if (mVideoWidth != 0 && mVideoHeight != 0) {
							getHolder().setFixedSize(mVideoWidth, mVideoHeight);
						}
					}
					if (mId != null) {
						mBrowser.eventList.run(EVENT_ONVIDEOSIZECHANGED, new String[]{mId, String.valueOf(width), String.valueOf(height)});
					} else {
						mBrowser.eventList.run(EVENT_ONVIDEOSIZECHANGED, new String[]{String.valueOf(width), String.valueOf(height)});
					}
				}
			});
			//mediaPlayer.setDataSource(path);
			mediaPlayer.setDataSource(mContext, uri);
			mediaPlayer.setDisplay(getHolder());
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mediaPlayer.setScreenOnWhilePlaying(true);
			mediaPlayer.prepareAsync();
		} catch (Exception e) {
			mBrowser.exception(CLASS_NAME, e);
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		if (isKeepScale) {
			int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
			int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
			if (mVideoWidth > 0 && mVideoHeight > 0) {
				if (mVideoWidth * height > width * mVideoHeight) {
					height = width * mVideoHeight / mVideoWidth;
				} else if (mVideoWidth * height < width * mVideoHeight) {
					width = height * mVideoWidth / mVideoHeight;
				} else {
				}
			}
			setMeasuredDimension(width, height);
		} else {
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		}
	}

	public static String decodeMediaError(int what, int extra) {
		String msg;
		switch (what) {
			case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK :
				msg = "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK";
				break;
			case MediaPlayer.MEDIA_ERROR_SERVER_DIED :
				msg = "MEDIA_ERROR_SERVER_DIED";
				break;
			case MediaPlayer.MEDIA_ERROR_UNKNOWN :
				msg = "MEDIA_ERROR_UNKNOWN";
				break;
			default :
				msg = "MEDIA_ERROR_UNKNOWN";
				break;
		}
		return msg;
	}
	public static String decodeMediaInfo(int what, int extra) {
		String msg;
		switch (what) {
			case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING :
				msg = "MEDIA_INFO_BAD_INTERLEAVING";
				break;
			case MediaPlayer.MEDIA_INFO_METADATA_UPDATE :
				msg = "MEDIA_INFO_METADATA_UPDATE";
				break;
			case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE :
				msg = "MEDIA_INFO_NOT_SEEKABLE";
				break;
			case MediaPlayer.MEDIA_INFO_UNKNOWN :
				msg = "MEDIA_INFO_UNKNOWN";
				break;
			case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING :
				msg = "MEDIA_INFO_VIDEO_TRACK_LAGGING";
				break;
			default :
				msg = "MEDIA_INFO_UNKNOWN";
				break;
		}
		return msg;
	}

}
